package com.weifly.weistock.record.bill;

import com.weifly.weistock.core.common.StockException;
import com.weifly.weistock.core.util.WeistockUtils;
import com.weifly.weistock.record.base.domain.RecordPair;
import com.weifly.weistock.record.bill.domain.StockRecordDto;

import java.util.ArrayList;
import java.util.List;

public class CalcStockContext {

    private int pairIndex = 1; // pair的索引值
    private List<RecordPair> pairList = new ArrayList<>(); // 匹配的pair列表

    private StockRecordDto currRecord; // 当前记录
    private BillConst.BusinessName currBusinessName; // 当前记录ot
    private int currTradeNumber; // 当前记录 剩余未配对数量

    public void initRecord(StockRecordDto recordDto){
        BillConst.BusinessName businessName = recordDto.getBusinessName();
        if(BillUtils.isCloseRecord(recordDto)){
            this.pairList.clear();
            this.currRecord = recordDto;
            this.currBusinessName = businessName;
            this.currTradeNumber = recordDto.getTradeNumber();
        }else{
            throw new StockException("不支持的businessName, " + businessName.getName());
        }
    }

    public void buildPair(StockRecordDto preRecord){
        // 没有“未配对”记录
        if(this.currTradeNumber<=0){
            return;
        }

        // 不是 证券买入记录
        if(!BillUtils.isOpenRecord(preRecord)){
            return;
        }

        // 没有成交数量
        if(preRecord.getTradeNumber()<=0){
            return;
        }

        // preRecord已配对完成
        int preNotPairNumber = BillUtils.getNotPairNumber(preRecord);
        if(preNotPairNumber<=0){
            return;
        }

        // 创建配对
        int pairNumber = this.currTradeNumber<=preNotPairNumber ? this.currTradeNumber : preNotPairNumber;
        RecordPair pairInfo = new RecordPair();
        pairInfo.setIndex(this.pairIndex);
        pairInfo.setNumber(pairNumber);
        this.addPairToRecord(preRecord, pairInfo);
        this.pairList.add(pairInfo);

        // 更新配对结算金额
        double currClearAmount = this.calcClearAmount(this.currRecord, pairNumber);
        double preClearAmount = this.calcClearAmount(preRecord, pairNumber);
        double addDiff = WeistockUtils.add(currClearAmount, preClearAmount);
        double currDiffAmount = this.currRecord.getDiffAmount()==null ? 0 : this.currRecord.getDiffAmount();
        this.currRecord.setDiffAmount(WeistockUtils.add(currDiffAmount, addDiff));

        // 修改变量
        this.currTradeNumber = this.currTradeNumber - pairNumber;
    }

    private void addPairToRecord(StockRecordDto record, RecordPair pair){
        List<RecordPair> pairList = record.getPairList();
        if(pairList==null){
            pairList = new ArrayList<>();
            record.setPairList(pairList);
        }
        pairList.add(pair);
    }

    private double calcClearAmount(StockRecordDto record, int pairNumber){
        if(pairNumber==record.getTradeNumber()){
            return record.getClearAmount();
        }
        return WeistockUtils.multi(WeistockUtils.divide(record.getClearAmount(), record.getTradeNumber()), pairNumber);
    }

    public int getCurrTradeNumber(){
        return this.currTradeNumber;
    }

    public void finishRecord(){
        if(this.pairList.size()>0){
            RecordPair currPair = new RecordPair();
            currPair.setIndex(this.pairIndex++);
            int totalNumber = 0;
            for(RecordPair prePair : this.pairList){
                totalNumber += prePair.getNumber();
            }
            currPair.setNumber(totalNumber);
            this.addPairToRecord(this.currRecord, currPair);
        }
    }
}
